#include <stdio.h>
#include <stdlib.h>
#include "sobjc/log.h"

static int objc_log_lv = OBJC_LOG_WARN;

static const char * const lv_names[] = {
  "trace",
  "debug",
  "info",
  "warn",
  "error",
  "fatal"
};

int objc_get_log_lv()
{
  return objc_log_lv;
}

void
objc_set_log_lv(int lv)
{
  if (lv < OBJC_LOG_TRACE || lv > OBJC_LOG_FATAL)
    objc_log_error("invalid log level -- %d", lv);
  else
    objc_log_lv = lv;
}

void
objc_log_msg(int lv, const char *format, ...)
{
  va_list ap;

  if (objc_log_lv <= lv) {
    va_start(ap, format);
    objc_log_msgv(lv, format, ap);
    va_end(ap);
  }
}

void
objc_log_msgv(int lv, const char *format, va_list ap)
{
  if (objc_log_lv <= lv) {
    if (lv < OBJC_LOG_TRACE || lv > OBJC_LOG_FATAL)
      objc_log_error("invalid log level -- %d", lv);
    printf("objc: %s: ", lv_names[lv]);
    vprintf(format, ap);
    printf("\n");
  }
}

void
objc_log_trace(const char *format, ...)
{
  va_list ap;

  if (objc_log_lv <= OBJC_LOG_TRACE) {
    va_start(ap, format);
    objc_log_msgv(OBJC_LOG_TRACE, format, ap);
    va_end(ap);
  }
}

void
objc_log_debug(const char *format, ...)
{
  va_list ap;

  if (objc_log_lv <= OBJC_LOG_DEBUG) {
    va_start(ap, format);
    objc_log_msgv(OBJC_LOG_DEBUG, format, ap);
    va_end(ap);
  }
}

void
objc_log_info(const char *format, ...)
{
  va_list ap;

  if (objc_log_lv <= OBJC_LOG_INFO) {
    va_start(ap, format);
    objc_log_msgv(OBJC_LOG_INFO, format, ap);
    va_end(ap);
  }
}

void
objc_log_warn(const char *format, ...)
{
  va_list ap;

  if (objc_log_lv <= OBJC_LOG_WARN) {
    va_start(ap, format);
    objc_log_msgv(OBJC_LOG_WARN, format, ap);
    va_end(ap);
  }
}

void
objc_log_error(const char *format, ...)
{
  va_list ap;

  if (objc_log_lv <= OBJC_LOG_ERROR) {
    va_start(ap, format);
    objc_log_msgv(OBJC_LOG_ERROR, format, ap);
    va_end(ap);
  }
}

void
objc_log_fatal(const char *format, ...)
{
  va_list ap;

  if (objc_log_lv <= OBJC_LOG_FATAL) {
    va_start(ap, format);
    objc_log_msgv(OBJC_LOG_FATAL, format, ap);
    va_end(ap);
  }
}

